package com.zmx.common.common.repository;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmx.common.common.dto.BaseDto;
import com.zmx.common.common.entitys.BaseEntity;
import com.zmx.common.common.utils.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 实体转换
 * @ClassName: TransformMapper
 * @Author zhaomxr
 * @Date 2021-09-29 10:32
 */
@Component
public class TransformMapper<TEntity extends BaseEntity, TDto extends BaseDto> {

    private final Logger logger = LoggerFactory.getLogger(TransformMapper.class);

    /**
     * 日期格式
     **/
    private static String DATE_FORMATE = "yyyy-mm-dd HH:mm:ss";

    /**
     * jackson 解析JSON方法 ObjectMapper
     **/
    private static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * Object转Json字符串
     *
     * @param object
     * @return
     */
    public String toJsonString(Object object) {
        if (Objects.isNull(object)) {
            return "";
        }
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            logger.info("{}", e);
            return "";
        }
    }

    /**
     * entity转dto
     *
     * @param entity
     * @return
     */
    public <TDto> TDto entityToDto(TEntity entity) {
        if (entity == null) {
            return null;
        }
        try {
            Class<? extends TDto> dtoClass = (Class<? extends TDto>) getDtoClass();
            return JacksonUtil.jsonStringToBean(toJsonString(entity), dtoClass);
        } catch (Exception e) {
            logger.error("{}", e);
            return null;
        }
    }

    /**
     * dto转entity
     *
     * @param entity
     * @return
     */
    public <TEntity> TEntity dtoToEntity(TDto dto) {
        if (dto == null) {
            return null;
        }
        try {
            Class<? extends TEntity> entityClass = (Class<? extends TEntity>) getEntityClass();
            return JacksonUtil.jsonStringToBean(toJsonString(dto), entityClass);
        } catch (Exception e) {
            logger.error("{}", e);
            return null;
        }
    }

    public <TDto> List<TDto> listToDtos(List entitys) {
        if (entitys == null || entitys.size() == 0) {
            return null;
        }
        return entityToDtos(JacksonUtil.toJsonString(entitys));
    }

    public <TDto> List<TDto> entityToDtos(List<TEntity> entitys) {
        if (entitys == null || entitys.size() == 0) {
            return null;
        }
        return entityToDtos(JacksonUtil.toJsonString(entitys));
    }

    /**
     * 批量entity转dto
     *
     * @param entitys
     * @param tClass
     * @return
     */
    public <TDto> List<TDto> entityToDtos(String jsonStr) {
        try {
            return objectMapper.readValue(jsonStr, new TypeReference<List<TDto>>() {
            });
        } catch (JsonProcessingException e) {
            logger.info("{}", e);
            return null;
        }
    }

    /**
     * 批量dto转entity
     *
     * @param entitys
     * @param tClass
     * @return
     */
    public <TEntity> List<TEntity> dtoToentitys(List<TDto> dtos) {
        if (dtos == null || dtos.size() == 0) {
            return null;
        }
        try {
            return objectMapper.readValue(JacksonUtil.toJsonString(dtos), new TypeReference<List<TEntity>>() {
            });
        } catch (JsonProcessingException e) {
            logger.info("{}", e);
            return null;
        }
    }

    protected Class<? extends TEntity> getEntityClass() {
        Class<? extends TEntity> entityClass = null;
        Class<?> clazz = getClass();
        while (!(clazz.getGenericSuperclass() instanceof ParameterizedType)) {
            clazz = clazz.getSuperclass();
        }
        Type entityType = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
        try {
            entityClass = (Class<? extends TEntity>) Class.forName(((Class) entityType).getName());
        } catch (ClassNotFoundException e) {
            logger.error("类无法找到", e);
        }
        return entityClass;
    }

    /**
     * 根据泛型获取Dto的类，如无泛型则通过父类的泛型获取，子类需要自定义Dto可重写本方法
     *
     * @return Dto的Class
     */
    protected Class<? extends TDto> getDtoClass() {
        Class<? extends TDto> dtoClass = null;
        Class<?> clazz = getClass();
        while (!(clazz.getGenericSuperclass() instanceof ParameterizedType)) {
            clazz = clazz.getSuperclass();
        }
        Type dtoType = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments()[1];
        try {
            dtoClass = (Class<TDto>) Class.forName(((Class) dtoType).getName());
        } catch (ClassNotFoundException e) {
            logger.error("类无法找到", e);
        }
        return dtoClass;
    }
}
